package org.jeecg.modules.waybill.service.impl;

import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
import org.dromara.easyes.core.conditions.update.LambdaEsUpdateWrapper;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.jeecg.boot.starter.lock.client.RedissonLockClient;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.LimitSubmit;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.UUIDGenerator;
import org.jeecg.config.wlhy.AmapClient;
import org.jeecg.modules.finance.api.JeecgFinanceApi;
import org.jeecg.modules.finance.entity.WlhyFreightSettlement;
import org.jeecg.modules.user.api.JeecgUserApi;
import org.jeecg.modules.user.entity.*;
import org.jeecg.modules.waybill.doc.WlhyWaybillDoc;
import org.jeecg.modules.waybill.doc_mapper.WlhyWaybillDocMapper;
import org.jeecg.modules.waybill.dto.WlhyWaybillDto;
import org.jeecg.modules.waybill.entity.WlhyWaybill;
import org.jeecg.modules.waybill.entity.WlhyWaybillDraft;
import org.jeecg.modules.waybill.mapper.WlhyWaybillMapper;
import org.jeecg.modules.waybill.service.IWlhyWaybillDraftService;
import org.jeecg.modules.waybill.service.IWlhyWaybillService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.Assert;

import javax.annotation.Resource;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static org.jeecg.common.constant.WlhyBizConstant.*;

/**
 * @Description: 订单表
 * @Author: jeecg-boot
 * @Date: 2024-04-11
 * @Version: V1.0
 */
@Service
@Slf4j
public class WlhyWaybillServiceImpl extends ServiceImpl<WlhyWaybillMapper, WlhyWaybill> implements IWlhyWaybillService {

    @Resource
    JeecgUserApi jeecgUserApi;
    @Resource
    JeecgFinanceApi jeecgFinanceApi;
    @Resource
    AmapClient amapClient;

    @Resource
    IWlhyWaybillDraftService wlhyWaybillDraftService;
    @Resource
    WlhyWaybillDocMapper wlhyWaybillDocMapper;
    @Resource
    TransactionTemplate transactionTemplate;
    @Resource
    RedissonLockClient redissonLockClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LimitSubmit(key = "downOrder:%s:#wlhyWaybill", limit = 2, needAllWait = true)
    public void downOrder(WlhyWaybill wlhyWaybill) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        // 检测企业状态
        Result<WlhyCompany> companyResult = jeecgUserApi.info();
        if (null == companyResult.getResult() || !COMPANY_AUTH_STATUS2.equals(companyResult.getResult().getAuthStatus())) {
            throw new RuntimeException("当前企业未认证,请认证后再次操作");
        }
        // 赋值公司信息
        wlhyWaybill.setCompanyLogo(companyResult.getResult().getCompanyLogo());
        wlhyWaybill.setCompanyName(companyResult.getResult().getCompanyName());
        wlhyWaybill.setCompanyId(companyResult.getResult().getId());
        // 检查提货时间和预计送达时间
        Assert.isTrue(wlhyWaybill.getDeliveryTime().getTime() > System.currentTimeMillis(), "提货时间不能早于当前时间");
        Assert.isTrue(wlhyWaybill.getEstArrivalTime().getTime() > System.currentTimeMillis(), "预计送达时间不能早于当前时间");
        // 检查代收款
        if (null != wlhyWaybill.getInvoicingFee() && wlhyWaybill.getInvoicingFee().compareTo(BigDecimal.ZERO) > 0) {

            if (StringUtils.isBlank(wlhyWaybill.getInvoicingPayMode())) {
                throw new RuntimeException("请选择代收款支付方式");
            }
        }

        // 生成订单号
        wlhyWaybill.setUserId(loginUser.getId());
        wlhyWaybill.setWaybillNo("Y" + UUIDGenerator.generate());
        wlhyWaybill.setId(IdWorker.getIdStr());
        // 解析 发货人 经纬度
        try {
            JSONArray shipAddrArray = amapClient.geocodeGeo(wlhyWaybill.getShipperAreaName() + wlhyWaybill.getShipperDetailAddr(), wlhyWaybill.getShipperAreaCode());
            log.info("解析 发货人 经纬度 {}", shipAddrArray);
            if (shipAddrArray.size() == 0) {
                throw new RuntimeException("未解析到发货人地理位置,请写详细一点重新提交表单");
            }
            JSONObject shipAddrObj = JSONObject.parseObject(JSON.toJSONString(shipAddrArray.get(0)));
            wlhyWaybill.setShipperLnglat(shipAddrObj.getString("location"));
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        }

        // 解析 收货人 经纬度
        try {
            JSONArray consignerAddrArray = amapClient.geocodeGeo(wlhyWaybill.getConsignerAreaName() + wlhyWaybill.getConsignerDetailAddr(), wlhyWaybill.getConsignerAreaCode());
            log.info("解析 收货人 经纬度 {}", consignerAddrArray);
            if (consignerAddrArray.size() == 0) {
                throw new RuntimeException("未解析到收货人地理位置,请写详细一点重新提交表单");
            }
            JSONObject consignerAddrObj = JSONObject.parseObject(JSON.toJSONString(consignerAddrArray.get(0)));
            wlhyWaybill.setConsignerLnglat(consignerAddrObj.getString("location"));
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        }

        // 是否指派司机
        if (1 == wlhyWaybill.getIzAssignDriver()) {
            AssertUtil.assertNotBlank(wlhyWaybill.getDriverUserId(), "接单用户不能为空");
            AssertUtil.assertNotBlank(wlhyWaybill.getDriverVehicleNo(), "司机车牌号不能为空");
            AssertUtil.assertNotBlank(wlhyWaybill.getDriverPhone(), "司机电话不能为空");
            AssertUtil.assertNotBlank(wlhyWaybill.getDriverName(), "司机姓名不能为空");
            AssertUtil.assertNotBlank(wlhyWaybill.getDriverBankHolder(), "司机银行开户名不能为空");
            AssertUtil.assertNotBlank(wlhyWaybill.getDriverBankCardNo(), "司机银行卡号不能为空");
            AssertUtil.assertNotBlank(wlhyWaybill.getDriverBankName(), "司机开户行不能为空");

            wlhyWaybill.setOrderTime(new Date());
            wlhyWaybill.setWaybillStatus(WAYBILL_STATUS2);

        } else {
            wlhyWaybill.setWaybillStatus(WAYBILL_STATUS1);
        }
        wlhyWaybill.setStatus(ROW_STATUS1);
        log.info("保存订单 {}", wlhyWaybill);
        Integer esInsert = wlhyWaybillDocMapper.insert(new WlhyWaybillDoc(wlhyWaybill));
        log.info("同步es {}", esInsert);
        // TODO 暂未添加事务 操作，此时也无所谓
        // 保存到常用发货人
        WlhyCompanyBothSides shipperSides = new WlhyCompanyBothSides()
                .setAreaCode(wlhyWaybill.getShipperAreaCode())
                .setAreaName(wlhyWaybill.getShipperAreaName())
                .setName(wlhyWaybill.getShipperName())
                .setPhone(wlhyWaybill.getShipperPhone())
                .setLnglat(wlhyWaybill.getShipperLnglat())
                .setDetailAddr(wlhyWaybill.getShipperDetailAddr())
                .setIdNum(wlhyWaybill.getShipperIdNum())
                .setCompanyId(companyResult.getResult().getId())
                .setSidesType(SIDES_TYPE1)
                .setStatus(ROW_STATUS1);

        jeecgUserApi.add(shipperSides);
        // 保存到常用收货人
        WlhyCompanyBothSides consignerSides = new WlhyCompanyBothSides()
                .setAreaCode(wlhyWaybill.getConsignerAreaCode())
                .setAreaName(wlhyWaybill.getConsignerAreaName())
                .setName(wlhyWaybill.getConsignerName())
                .setPhone(wlhyWaybill.getConsignerPhone())
                .setLnglat(wlhyWaybill.getConsignerLnglat())
                .setDetailAddr(wlhyWaybill.getConsignerDetailAddr())
                .setIdNum(wlhyWaybill.getConsignerIdNum())
                .setCompanyId(companyResult.getResult().getId())
                .setSidesType(SIDES_TYPE2)
                .setStatus(ROW_STATUS1);
        jeecgUserApi.add(consignerSides);

        save(wlhyWaybill);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)

    public void deleteByIds(List<String> ids) {
        // 只能删除待接单的
        update(new LambdaUpdateWrapper<WlhyWaybill>().in(WlhyWaybill::getId, ids)
                .eq(WlhyWaybill::getWaybillStatus, WAYBILL_STATUS1)
                .set(WlhyWaybill::getStatus, ROW_STATUS3));

        Integer esUpdate = wlhyWaybillDocMapper.update(null, new LambdaEsUpdateWrapper<WlhyWaybillDoc>()
                .in(WlhyWaybillDoc::getId, ids)
                .eq(WlhyWaybillDoc::getWaybillStatus, WAYBILL_STATUS1)
                .set(WlhyWaybillDoc::getStatus, ROW_STATUS3)
        );
        log.info("同步 esUpdate {}", esUpdate);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)

    public void deleteById(String id) {
        // 只能删除待接单的
        update(new LambdaUpdateWrapper<WlhyWaybill>().eq(WlhyWaybill::getId, id)
                .eq(WlhyWaybill::getWaybillStatus, WAYBILL_STATUS1)
                .set(WlhyWaybill::getStatus, ROW_STATUS3));

        Integer esUpdate = wlhyWaybillDocMapper.update(null, new LambdaEsUpdateWrapper<WlhyWaybillDoc>()
                .eq(WlhyWaybillDoc::getId, id)
                .eq(WlhyWaybillDoc::getWaybillStatus, WAYBILL_STATUS1)
                .set(WlhyWaybillDoc::getStatus, ROW_STATUS3)
        );
        log.info("同步 esUpdate {}", esUpdate);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)

    public void completeDelete(String id) {
        //  只能把回收站中的订单 进行彻底删除
        update(new LambdaUpdateWrapper<WlhyWaybill>().eq(WlhyWaybill::getId, id)
                .eq(WlhyWaybill::getStatus, ROW_STATUS3)
                .set(WlhyWaybill::getStatus, ROW_STATUS0));

        Integer esUpdate = wlhyWaybillDocMapper.update(null, new LambdaEsUpdateWrapper<WlhyWaybillDoc>()
                .eq(WlhyWaybillDoc::getId, id)
                .set(WlhyWaybillDoc::getStatus, ROW_STATUS3)
        );
        log.info("同步 esUpdate {}", esUpdate);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)

    public void completeDeleteBatch(List<String> ids) {
        //  只能把回收站中的订单 进行彻底删除
        update(new LambdaUpdateWrapper<WlhyWaybill>()
                .in(WlhyWaybill::getId, ids)
                .eq(WlhyWaybill::getStatus, ROW_STATUS3)
                .set(WlhyWaybill::getStatus, ROW_STATUS0));
        Integer esUpdate = wlhyWaybillDocMapper.update(null, new LambdaEsUpdateWrapper<WlhyWaybillDoc>()
                .in(WlhyWaybillDoc::getId, ids)
                .eq(WlhyWaybillDoc::getStatus, ROW_STATUS3)
                .set(WlhyWaybillDoc::getStatus, ROW_STATUS0)
        );
        log.info("同步 esUpdate {}", esUpdate);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void revoke(String id) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        // 彻底删除
        completeDelete(id);
        // 添加到草稿箱
        WlhyWaybill waybill = getById(id);
        WlhyWaybillDraft wlhyWaybillDraft = new WlhyWaybillDraft();
        BeanUtils.copyProperties(waybill, wlhyWaybillDraft);
        wlhyWaybillDraft.setUserId(loginUser.getId());
        wlhyWaybillDraft.setCreateBy(null);
        wlhyWaybillDraft.setCreateTime(null);
        wlhyWaybillDraft.setUpdateBy(null);
        wlhyWaybillDraft.setUpdateTime(null);
        wlhyWaybillDraft.setStatus(ROW_STATUS1);
        wlhyWaybillDraftService.save(wlhyWaybillDraft);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void revokeBatch(List<String> ids) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        // 彻底删除
        completeDeleteBatch(ids);
        // 添加到草稿箱
        List<WlhyWaybillDraft> draftList = new ArrayList();
        for (String id : ids) {
            WlhyWaybill waybill = getById(id);
            if (null == waybill) {
                continue;
            }
            WlhyWaybillDraft wlhyWaybillDraft = new WlhyWaybillDraft();
            BeanUtils.copyProperties(waybill, wlhyWaybillDraft);
            wlhyWaybillDraft.setUserId(loginUser.getId());
            wlhyWaybillDraft.setCreateBy(null);
            wlhyWaybillDraft.setCreateTime(null);
            wlhyWaybillDraft.setUpdateBy(null);
            wlhyWaybillDraft.setUpdateTime(null);
            wlhyWaybillDraft.setStatus(ROW_STATUS1);

            draftList.add(wlhyWaybillDraft);

        }
        wlhyWaybillDraftService.saveBatch(draftList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void expireJobHandler() {
        // 查询 正常 待接单 提货时间大于当前时间 的订单
        List<WlhyWaybill> list = list(new LambdaQueryWrapper<WlhyWaybill>()
                .eq(WlhyWaybill::getStatus, ROW_STATUS1)
                .eq(WlhyWaybill::getWaybillStatus, WAYBILL_STATUS1)
                .le(WlhyWaybill::getDeliveryTime, LocalDateTime.now())
        );
        for (WlhyWaybill wlhyWaybill : list) {
            update(new LambdaUpdateWrapper<WlhyWaybill>()
                    .eq(WlhyWaybill::getId, wlhyWaybill.getId())
                    .set(WlhyWaybill::getWaybillStatus, WAYBILL_STATUS7)
            );
        }
    }

    @Override
    public IPage<WlhyWaybillDoc> search(WlhyWaybillDto waybillDto, Integer pageNo, Integer pageSize) {

       /* Page<WlhyWaybill> page = new Page<WlhyWaybill>(pageNo, pageSize);
        waybillDto.setWaybillStatus(WAYBILL_STATUS1);
        List<WlhyWaybillVo> pageList = baseMapper.pageList(page, waybillDto);

        Page<WlhyWaybillVo> voPage = new Page<WlhyWaybillVo>(pageNo, pageSize);
        BeanUtils.copyProperties(page,voPage);
        voPage.setRecords(pageList);
           return voPage;
        */
        LambdaEsQueryWrapper<WlhyWaybillDoc> wrapper = new LambdaEsQueryWrapper<WlhyWaybillDoc>()
                .and(StringUtils.isNotBlank(waybillDto.getKeyword()), lwq ->
                        lwq.like(WlhyWaybillDoc::getWaybillNo, waybillDto.getKeyword())
                                .or()
                                .like(WlhyWaybillDoc::getCompanyName, waybillDto.getKeyword())
                                .or()
                                .like(WlhyWaybillDoc::getShipperAreaName, waybillDto.getKeyword())
                                .or()
                                .like(WlhyWaybillDoc::getShipperDetailAddr, waybillDto.getKeyword())
                                .or()
                                .like(WlhyWaybillDoc::getConsignerAreaName, waybillDto.getKeyword())
                                .or()
                                .like(WlhyWaybillDoc::getConsignerDetailAddr, waybillDto.getKeyword()))
                .filter(lwq -> lwq
                        .geoDistance(WlhyWaybillDoc::getShipperLnglat, 100000.0, DistanceUnit.KILOMETERS, new GeoPoint(waybillDto.getLat(), waybillDto.getLng()))
                        .eq(WlhyWaybillDoc::getStatus, ROW_STATUS1)
                        .eq(StringUtils.isNotBlank(waybillDto.getWaybillStatus()), WlhyWaybillDoc::getWaybillStatus, waybillDto.getWaybillStatus())
                )
                .orderByDistanceAsc(WlhyWaybillDoc::getShipperLnglat, DistanceUnit.KILOMETERS, new GeoPoint(waybillDto.getLat(), waybillDto.getLng()))
                .limit((pageNo - 1) * pageSize, pageSize);
//        SearchResponse search = wlhyWaybillDocMapper.search(wrapper);
        List<WlhyWaybillDoc> wlhyWaybillDocs = wlhyWaybillDocMapper.selectList(wrapper);
        log.info("查询结果 数量 {}", wlhyWaybillDocs.size());
        wlhyWaybillDocs.forEach(System.out::println);
        Page<WlhyWaybillDoc> page = new Page<WlhyWaybillDoc>(pageNo, pageSize);
        page.setRecords(wlhyWaybillDocs);
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(WlhyWaybill wlhyWaybill) {
        WlhyWaybill waybill = getById(wlhyWaybill.getId());
        if (null == waybill) {
            throw new RuntimeException("订单不存在");
        }
       /* if (!WAYBILL_STATUS1.equals(waybill.getWaybillStatus())) {
            throw new RuntimeException("此状态的订单禁止编辑");
        }*/
        // todo 不同状态 编辑内容不同
        updateById(waybill);
        Integer esUpdate = wlhyWaybillDocMapper.updateById(new WlhyWaybillDoc(wlhyWaybill));
        log.info("esUpdate {} ", esUpdate);


    }

    @Override
    public void skillOrder(String waybillId) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        // 司机校验
        // 1 是否存在默认银行卡
        Result<WlhyUserBank> bankResult = jeecgUserApi.myDefaultBank();
        WlhyUserBank driverBank = bankResult.getResult();
        if (null == driverBank) {
            throw new RuntimeException("请添加银行卡");
        }

        // 2 是否车辆认证
        Result<WlhyVehicle> vehicleResult = jeecgUserApi.myVehicle();
        WlhyVehicle vehicle = vehicleResult.getResult();
        if (null == vehicle || !VEHICLE_STATUS3.equals(vehicle.getVehicleStatus())) {
            throw new RuntimeException("请认证车辆,认证成功后,才可以接单");
        }
        // 订单校验
        WlhyWaybill waybill = getById(waybillId);
        if (null == waybill) {
            throw new RuntimeException("订单不存在");
        }
        if (!ROW_STATUS1.equals(waybill.getStatus())) {
            throw new RuntimeException("当前订单已被删除");
        }
        if (!WAYBILL_STATUS1.equals(waybill.getWaybillStatus())) {
            throw new RuntimeException("当前订单已被接单");
        }
        if (redissonLockClient.tryLock(String.format("skillOrder:%s", waybillId), -1, 10000)) {
            try {
                transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                    @Override
                    protected void doInTransactionWithoutResult(TransactionStatus status) {
                        // 更新
                        update(new LambdaUpdateWrapper<WlhyWaybill>()
                                .eq(WlhyWaybill::getId, waybillId)
                                .set(WlhyWaybill::getDriverBankCardNo, driverBank.getBankCardNo())
                                .set(WlhyWaybill::getDriverBankHolder, driverBank.getBankHolder())
                                .set(WlhyWaybill::getDriverBankName, driverBank.getBankName())
                                .set(WlhyWaybill::getDriverBankId, driverBank.getId())
                                .set(WlhyWaybill::getDriverUserId, loginUser.getId())
                                .set(WlhyWaybill::getDriverName, driverBank.getBankHolder())
                                .set(WlhyWaybill::getDriverPhone, loginUser.getPhone())
                                .set(WlhyWaybill::getDriverVehicleNo, vehicle.getDrivingFVehicleNo())
                                .set(WlhyWaybill::getOrderTime, new Date())
                                .set(WlhyWaybill::getWaybillStatus, WAYBILL_STATUS2)
                        );
                        // 同步es
                        Integer EsUpdate = wlhyWaybillDocMapper.update(new WlhyWaybillDoc()
                                        .setDriverBankCardNo(driverBank.getBankCardNo())
                                        .setDriverBankHolder(driverBank.getBankHolder())
                                        .setDriverBankName(driverBank.getBankName())
                                        .setDriverBankId(driverBank.getId())
                                        .setDriverUserId(loginUser.getId())
                                        .setDriverName(driverBank.getBankHolder())
                                        .setDriverPhone(loginUser.getPhone())
                                        .setDriverVehicleNo(vehicle.getDrivingFVehicleNo())
                                        .setOrderTime(new Date())
                                        .setWaybillStatus(WAYBILL_STATUS2)
                                , new LambdaEsUpdateWrapper<WlhyWaybillDoc>().eq(WlhyWaybillDoc::getId, waybillId));
                        if (0 == EsUpdate) {
                            throw new RuntimeException("更新失败");
                        }

                    }
                });

                // 保存常用司机表 TODO 无需加入事务，无所谓
                WlhyCompanyDriver driver = new WlhyCompanyDriver()
                        .setCompanyId(waybill.getCompanyId())
                        .setWaybillPubUserId(waybill.getUserId())
                        .setDriverUserId(loginUser.getId())
                        .setDriverVehicleNo(vehicle.getDrivingFVehicleNo())
                        .setDriverPhone(loginUser.getPhone())
                        .setDriverName(driverBank.getBankHolder())
                        .setDriverBankId(driverBank.getId())
                        .setDriverBankHolder(driverBank.getBankHolder())
                        .setDriverBankCardNo(driverBank.getBankCardNo())
                        .setDriverBankName(driverBank.getBankName());
                jeecgUserApi.addCompanyDriver(driver);
            } finally {
                redissonLockClient.unlock(String.format("skillOrder:%s", waybillId));
            }
        } else {
            throw new RuntimeException("订单太火爆了，请稍后再试");
        }


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void loadCargo(String waybillId) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        WlhyWaybill wlhyWaybill = getById(waybillId);
        if (!WAYBILL_STATUS2.equals(wlhyWaybill.getWaybillStatus())) {
            throw new RuntimeException("此订单已装货");
        }
        // 只有运单创建人 和 司机可以操作发货
        if (wlhyWaybill.getUserId().equals(loginUser.getId()) || wlhyWaybill.getDriverUserId().equals(loginUser.getId())) {
            update(new LambdaUpdateWrapper<WlhyWaybill>().eq(WlhyWaybill::getId, waybillId).set(WlhyWaybill::getWaybillStatus, WAYBILL_STATUS3));
            Integer update = wlhyWaybillDocMapper.update(null, new LambdaEsUpdateWrapper<WlhyWaybillDoc>().eq(WlhyWaybillDoc::getId, waybillId).set(WlhyWaybillDoc::getWaybillStatus, WAYBILL_STATUS3));
            if (0 == update) {
                throw new RuntimeException("装货失败，请联系客服");
            }
            return;
        }
        throw new RuntimeException("非法操作");

    }

    @Override
    public void startCar(String waybillId) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        WlhyWaybill wlhyWaybill = getById(waybillId);
        if (!WAYBILL_STATUS3.equals(wlhyWaybill.getWaybillStatus())) {
            throw new RuntimeException("此订单已发车");
        }
        // 只有司机可以操作发车
        if (wlhyWaybill.getDriverUserId().equals(loginUser.getId())) {
            update(new LambdaUpdateWrapper<WlhyWaybill>().eq(WlhyWaybill::getId, waybillId).set(WlhyWaybill::getWaybillStatus, WAYBILL_STATUS4));
            Integer update = wlhyWaybillDocMapper.update(null, new LambdaEsUpdateWrapper<WlhyWaybillDoc>().eq(WlhyWaybillDoc::getId, waybillId).set(WlhyWaybillDoc::getWaybillStatus, WAYBILL_STATUS4));
            if (0 == update) {
                throw new RuntimeException("发车失败，请联系客服");
            }
            return;
        }
        throw new RuntimeException("非法操作");

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LimitSubmit(key = "signFor:%s:#waybillId", limit = 2, needAllWait = true)
    public void signFor(String waybillId) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        WlhyWaybill wlhyWaybill = getById(waybillId);
        if (!WAYBILL_STATUS4.equals(wlhyWaybill.getWaybillStatus())) {
            throw new RuntimeException("此订单已签收");
        }
        // 只有收货人可以签收
        if (wlhyWaybill.getConsignerPhone().equals(loginUser.getPhone())) {
            // 如果此运单没有代收款，直接签收  TODO 需要加分布式事务处理
            if (null == wlhyWaybill.getInvoicingFee() || wlhyWaybill.getInvoicingFee().compareTo(BigDecimal.ZERO) <= 0) {
                update(new LambdaUpdateWrapper<WlhyWaybill>().eq(WlhyWaybill::getId, waybillId).set(WlhyWaybill::getWaybillStatus, WAYBILL_STATUS5));
                Integer update = wlhyWaybillDocMapper.update(null, new LambdaEsUpdateWrapper<WlhyWaybillDoc>().eq(WlhyWaybillDoc::getId, waybillId).set(WlhyWaybillDoc::getWaybillStatus, WAYBILL_STATUS5));
                if (0 == update) {
                    throw new RuntimeException("签收失败，请联系客服");
                }
                // TODO 当前订单进入财务管理 结算司机运费
                WlhyFreightSettlement wlhyFreightSettlement = new WlhyFreightSettlement();
                BeanUtils.copyProperties(wlhyWaybill, wlhyFreightSettlement);
                wlhyFreightSettlement.setId(null);
                wlhyFreightSettlement.setSettleFreightStatus(SETTLE_FREIGHT_STATUS1);
                wlhyFreightSettlement.setStatus(ROW_STATUS1);
                wlhyFreightSettlement.setWaybillId(wlhyWaybill.getId());
                wlhyFreightSettlement.setWaybillNo(wlhyWaybill.getWaybillNo());
                wlhyFreightSettlement.setOrderUserId(wlhyWaybill.getUserId());
                Result<String> freightSettlement = jeecgFinanceApi.addFreightSettlement(wlhyFreightSettlement);
                if (!freightSettlement.isSuccess()) {
                    throw new RuntimeException("签收失败，请联系客服");
                }
            } else {
                // TODO 拉起支付
            }
            return;
        }
        throw new RuntimeException("非法操作");
    }
}
